use std::{fs::File, io::Read};

static mut PRIMES: Vec<u32> = Vec::new();
static mut PRIME_INDEX: usize = 0;
static mut FILE_INDEX: usize = 0;

fn init(no: usize) -> Vec<u32> {
    let mut buf = String::with_capacity(12 * 1024 * 1024);
    let fileno = format!("./prime{:02}.txt", no);
    let mut f = File::open(fileno).unwrap();
    f.read_to_string(&mut buf).unwrap();
    buf.split(',')
        .filter_map(|e| Some(e.parse::<u32>().unwrap()))
        .collect()
}

fn next_prime() -> u32 {
    unsafe {
        if PRIME_INDEX >= PRIMES.len() {
            FILE_INDEX += 1;
            if FILE_INDEX > 3 {
                return u32::MAX;
            }
            PRIMES = init(FILE_INDEX);
            PRIME_INDEX = 0;
        }
        let res = *PRIMES.get_unchecked(PRIME_INDEX);
        PRIME_INDEX += 1;
        res
    }
}

pub fn min_edge_prime_num(number: u32) -> String {
    let mut prime_nums = 0;
    let ratio_bound = (number as f32) / 100.0;
    let mut total_nums = 1;

    unsafe {
        PRIME_INDEX = 0;
        FILE_INDEX = 0;
        PRIMES = init(FILE_INDEX);
        FILE_INDEX += 1;
    }
    let mut np = next_prime();

    for n in (3..).step_by(2) {
        total_nums += 4;
        let spiral_nums = (n * n - 3 * (n - 1), n * n - 2 * (n - 1), n * n - (n - 1));
        while np < spiral_nums.0 {
            np = next_prime();
        }
        if np == spiral_nums.0 {
            prime_nums += 1;
            np = next_prime();
        }
        while np < spiral_nums.1 {
            np = next_prime();
        }
        if np == spiral_nums.1 {
            prime_nums += 1;
            np = next_prime();
        }
        while np < spiral_nums.2 {
            np = next_prime();
        }
        if np == spiral_nums.2 {
            prime_nums += 1;
            np = next_prime();
        }
        if np == u32::MAX {
            return "".to_string();
        }
        if (prime_nums as f32) / (total_nums as f32) < ratio_bound {
            return format!("{},{}", n, prime_nums);
        }
    }
    unreachable!()
}
